package com.diao.myhub.controller;

import com.diao.myhub.asserts.ServiceAsserts;
import com.diao.myhub.exception.CustomizeError;
import com.diao.myhub.exception.CustomizeException;
import com.diao.myhub.model.dto.AccessTokenDTO;
import com.diao.myhub.model.po.User;
import com.diao.myhub.model.vo.LoginTypeVO;
import com.diao.myhub.service.UserService;
import com.diao.myhub.strategy.DTO.LoginUser;
import com.diao.myhub.strategy.UserLoginFactory;
import com.diao.myhub.strategy.UserStrategy;
import com.diao.myhub.util.JsonUtil;
import com.diao.myhub.util.RequestUtils;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@RestController
@RequiredArgsConstructor
@Slf4j
public class AuthController {
    private final List<UserStrategy> userStrategies;
    private final UserLoginFactory loginFactory;
    private final UserService userService;
    @Value("${front-end.redirect.address}")
    private String frontRedirectUrl;

    @GetMapping("/login/types")
    public List<LoginTypeVO> getLoginTypes() {
        return userStrategies.stream().map(stg -> {
            LoginTypeVO loginTypeVO = new LoginTypeVO();
            loginTypeVO.setRedirectUrl(stg.getRedirectUri2());
            loginTypeVO.setType(stg.getType());
            return loginTypeVO;
        }).toList();
    }

    @GetMapping("/login/callback")
    public String callback(
            HttpServletRequest request,
            HttpServletResponse response,
            String code,
            String loginType) throws Exception {
        if (Objects.isNull(loginType)) {
            loginType = "gitee";
        }
        ServiceAsserts.notBlank(code, "登录码不能为空");
        AccessTokenDTO tokenDTO = new AccessTokenDTO();
        tokenDTO.setCode(code);
        UserStrategy loginStrategy = loginFactory.getLoginStrategy(loginType);
        LoginUser loginUser = loginStrategy.getLoginUserType2(tokenDTO);
        if (loginUser != null) {
            // 查询用户是否曾经登陆过
            User user = userService.getUserByAccountId(loginType + loginUser.getId());
            String token = UUID.randomUUID().toString().replace("-", "");
            // 曾经登录过,更新token
            if (user != null) {
                user.setToken(token);
                userService.updateToken(user.getId(), token);
            } else {
                // 未登录则创建新用户
                user = createUserByLoginUser(loginType, loginUser);
                user.setToken(token);
                userService.addUser(user);
            }
            // 无论是否登录过,都会创建cookie和session
            request.getSession().setAttribute("user", user);
            Cookie clientToken = new Cookie("token", token);
            user.setAccountId(null);
            Cookie userInfo = new Cookie("user", URLEncoder.encode(JsonUtil.toJson(user), Charset.defaultCharset()));
            clientToken.setMaxAge(2_592_000);
            clientToken.setPath("/");
            response.addCookie(clientToken);
            userInfo.setPath("/");
            userInfo.setMaxAge(2_592_000);
            response.addCookie(userInfo);
        } else {
            log.info("获取用户信息失败");
            throw new CustomizeException(CustomizeError.LOGIN_FAILED);
        }
        response.sendRedirect(RequestUtils.getDomain());
        return "";
    }
    @GetMapping("/login/out")
    public String loginOut(HttpServletRequest request, HttpServletResponse response) {
        request.getSession().removeAttribute("user");

        Cookie cookie = new Cookie("token",null);
        cookie.setMaxAge(0);
        cookie.setPath("/");
        response.addCookie(cookie);

        Cookie userInfo = new Cookie("user", null);
        userInfo.setPath("/");
        userInfo.setMaxAge(0);
        response.addCookie(userInfo);

        return "ok";
    }
    private User createUserByLoginUser(String type,LoginUser loginUser){
        User user = new User();
        user.setName(loginUser.getName());
        user.setAccountId(type+loginUser.getId());
        user.setGmtCreate(System.currentTimeMillis());
        user.setGmtModify(user.getGmtCreate());
        user.setBio(loginUser.getBio());
        user.setAvatarUrl(loginUser.getAvatar_url());
        return user;
    }
}
